home *** CD-ROM | disk | FTP | other *** search
- /* "intern" and friends -- moved here from lread.c
- Copyright (C) 1985-1989, 1992-1994 Free Software Foundation, Inc.
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: FSF 19.28. */
-
- /* This file has been Mule-ized. */
-
- /* #### Ugh, though, this file does awful things with symbol-value-magic
- objects. This ought to be cleaned up. */
-
- #include <config.h>
- #include "lisp.h"
- #include "symeval.h"
- #include "buffer.h" /* for Vbuffer_defaults */
-
- Lisp_Object Qad_advice_info, Qad_activate;
-
-
- #ifdef LRECORD_SYMBOL
-
- static Lisp_Object mark_symbol (Lisp_Object, void (*) (Lisp_Object));
- extern void print_symbol (Lisp_Object, Lisp_Object, int);
- DEFINE_LRECORD_IMPLEMENTATION ("symbol", symbol,
- mark_symbol, print_symbol, 0, 0, 0,
- struct Lisp_Symbol);
-
- static Lisp_Object
- mark_symbol (Lisp_Object obj, void (*markobj) (Lisp_Object))
- {
- struct Lisp_Symbol *sym = XSYMBOL (obj);
- Lisp_Object pname;
-
- ((markobj) (sym->value));
- ((markobj) (sym->function));
- XSETSTRING (pname, sym->name);
- ((markobj) (pname));
- if (!symbol_next (sym))
- return (sym->plist);
- else
- {
- ((markobj) (sym->plist));
- /* Mark the rest of the symbols in the obarray hash-chain */
- sym = symbol_next (sym);
- XSETSYMBOL (obj, sym);
- return (obj);
- }
- }
-
- #endif /* LRECORD_SYMBOL */
-
-
- /**********************************************************************/
- /* Intern */
- /**********************************************************************/
-
- Lisp_Object Vobarray;
-
- static Lisp_Object initial_obarray;
-
- static Lisp_Object
- check_obarray (Lisp_Object obarray)
- {
- while (!VECTORP (obarray) || vector_length (XVECTOR (obarray)) == 0)
- {
- /* If Vobarray is now invalid, force it to be valid. */
- if (EQ (Vobarray, obarray)) Vobarray = initial_obarray;
-
- obarray = wrong_type_argument (Qvectorp, obarray);
- }
- return obarray;
- }
-
- Lisp_Object
- intern (CONST char *str)
- {
- Lisp_Object tem;
- Bytecount len = strlen (str);
- Lisp_Object obarray = Vobarray;
- if (!VECTORP (obarray) || vector_length (XVECTOR (obarray)) == 0)
- obarray = check_obarray (obarray);
- tem = oblookup (obarray, (CONST Bufbyte *) str, len);
-
- if (SYMBOLP (tem))
- return tem;
- return Fintern (((purify_flag)
- ? make_pure_pname ((Bufbyte *) str, len, 0)
- : make_string ((Bufbyte *) str, len)),
- obarray);
- }
-
- DEFUN ("intern", Fintern, Sintern, 1, 2, 0,
- "Return the canonical symbol whose name is STRING.\n\
- If there is none, one is created by this function and returned.\n\
- A second optional argument specifies the obarray to use;\n\
- it defaults to the value of `obarray'.")
- (str, obarray)
- Lisp_Object str, obarray;
- {
- Lisp_Object sym, *ptr;
- Bytecount len;
-
- if (NILP (obarray)) obarray = Vobarray;
- obarray = check_obarray (obarray);
-
- CHECK_STRING (str, 0);
-
- len = string_length (XSTRING (str));
- sym = oblookup (obarray, string_data (XSTRING (str)), len);
- if (!INTP (sym))
- /* Found it */
- return sym;
-
- ptr = &vector_data (XVECTOR (obarray))[XINT (sym)];
-
- if (purify_flag && ! purified (str))
- str = make_pure_pname (string_data (XSTRING (str)), len, 0);
- sym = Fmake_symbol (str);
-
- if (SYMBOLP (*ptr))
- symbol_next (XSYMBOL (sym)) = XSYMBOL (*ptr);
- else
- symbol_next (XSYMBOL (sym)) = 0;
- *ptr = sym;
- return sym;
- }
-
- DEFUN ("intern-soft", Fintern_soft, Sintern_soft, 1, 2, 0,
- "Return the canonical symbol whose name is STRING, or nil if none exists.\n\
- A second optional argument specifies the obarray to use;\n\
- it defaults to the value of `obarray'.")
- (str, obarray)
- Lisp_Object str, obarray;
- {
- Lisp_Object tem;
-
- if (NILP (obarray)) obarray = Vobarray;
- obarray = check_obarray (obarray);
-
- CHECK_STRING (str, 0);
-
- tem = oblookup (obarray, string_data (XSTRING (str)),
- string_length (XSTRING (str)));
- if (!INTP (tem))
- return tem;
- return Qnil;
- }
-
- Lisp_Object
- oblookup (Lisp_Object obarray, CONST Bufbyte *ptr, Bytecount size)
- {
- int hash, obsize;
- struct Lisp_Symbol *tail;
- Lisp_Object bucket;
-
- while (!VECTORP (obarray) ||
- (obsize = vector_length (XVECTOR (obarray))) == 0)
- {
- obarray = check_obarray (obarray);
- }
- /* Combining next two lines breaks VMS C 2.3. */
- hash = hash_string (ptr, size);
- hash %= obsize;
- bucket = vector_data (XVECTOR (obarray))[hash];
- if (XINT (bucket) == 0)
- ;
- else if (!SYMBOLP (bucket))
- error ("Bad data in guts of obarray"); /* Like CADR error message */
- else
- for (tail = XSYMBOL (bucket); ;)
- {
- if (string_length (tail->name) == size &&
- !memcmp (string_data (tail->name), ptr, size))
- {
- XSETSYMBOL (bucket, tail);
- return (bucket);
- }
- tail = symbol_next (tail);
- if (!tail)
- break;
- }
- return (make_number (hash));
- }
-
- int
- hash_string (CONST Bufbyte *ptr, Bytecount len)
- {
- CONST Bufbyte *p = ptr;
- CONST Bufbyte *end = p + len;
- Bufbyte c;
- int hash = 0;
-
- while (p != end)
- {
- c = *p++;
- if (c >= 0140) c -= 40;
- hash = ((hash<<3) + (hash>>28) + c);
- }
- return hash & 07777777777;
- }
-
- void
- map_obarray (Lisp_Object obarray,
- void (*fn) (Lisp_Object sym, Lisp_Object arg),
- Lisp_Object arg)
- {
- int i;
- Lisp_Object tail;
- CHECK_VECTOR (obarray, 1);
- for (i = vector_length (XVECTOR (obarray)) - 1; i >= 0; i--)
- {
- tail = vector_data (XVECTOR (obarray))[i];
- if (SYMBOLP (tail))
- while (1)
- {
- struct Lisp_Symbol *next;
- (*fn) (tail, arg);
- next = symbol_next (XSYMBOL (tail));
- if (!next)
- break;
- XSETSYMBOL (tail, next);
- }
- }
- }
-
- static void
- mapatoms_1 (Lisp_Object sym, Lisp_Object function)
- {
- call1 (function, sym);
- }
-
- DEFUN ("mapatoms", Fmapatoms, Smapatoms, 1, 2, 0,
- "Call FUNCTION on every symbol in OBARRAY.\n\
- OBARRAY defaults to the value of `obarray'.")
- (function, obarray)
- Lisp_Object function, obarray;
- {
- if (NILP (obarray))
- obarray = Vobarray;
- obarray = check_obarray (obarray);
-
- map_obarray (obarray, mapatoms_1, function);
- return Qnil;
- }
-
-
- /**********************************************************************/
- /* Apropos */
- /**********************************************************************/
-
- static void
- apropos_accum (Lisp_Object symbol, Lisp_Object arg)
- {
- Lisp_Object tem;
- Lisp_Object string = XCAR (arg);
- Lisp_Object predicate = XCAR (XCDR (arg));
- Lisp_Object *accumulation = &(XCDR (XCDR (arg)));
-
- tem = Fstring_match (string, Fsymbol_name (symbol), Qnil);
- if (!NILP (tem) && !NILP (predicate))
- tem = call1 (predicate, symbol);
- if (!NILP (tem))
- *accumulation = Fcons (symbol, *accumulation);
- }
-
- DEFUN ("apropos-internal", Fapropos_internal, Sapropos_internal, 1, 2, 0,
- "Show all symbols whose names contain match for REGEXP.\n\
- If optional 2nd arg PRED is non-nil, (funcall PRED SYM) is done\n\
- for each symbol and a symbol is mentioned only if that returns non-nil.\n\
- Return list of symbols found.")
- (string, pred)
- Lisp_Object string, pred;
- {
- struct gcpro gcpro1;
- Lisp_Object accumulation;
-
- CHECK_STRING (string, 0);
- accumulation = Fcons (string, Fcons (pred, Qnil));
- GCPRO1 (accumulation);
- map_obarray (Vobarray, apropos_accum, accumulation);
- accumulation = Fsort (Fcdr (Fcdr (accumulation)), Qstring_lessp);
- UNGCPRO;
- return (accumulation);
- }
-
-
- /* Extract and set components of symbols */
-
- static Lisp_Object swap_in_symval_forwarding
- (Lisp_Object sym, struct symbol_value_buffer_local *);
-
- DEFUN ("boundp", Fboundp, Sboundp, 1, 1, 0, "T if SYMBOL's value is not void.")
- (sym)
- Lisp_Object sym;
- {
- CHECK_SYMBOL (sym, 0);
- return (EQ (find_symbol_value (sym), Qunbound) ? Qnil : Qt);
- }
-
- DEFUN ("globally-boundp", Fglobally_boundp, Sglobally_boundp, 1, 1, 0,
- "T if SYMBOL has a global (non-bound) value.\n\
- This is for the byte-compiler; you really shouldn't be using this.")
- (sym)
- Lisp_Object sym;
- {
- CHECK_SYMBOL (sym, 0);
- return (EQ (top_level_value (sym), Qunbound) ? Qnil : Qt);
- }
-
- DEFUN ("fboundp", Ffboundp, Sfboundp, 1, 1, 0,
- "T if SYMBOL's function definition is not void.")
- (sym)
- Lisp_Object sym;
- {
- CHECK_SYMBOL (sym, 0);
- return ((EQ (XSYMBOL (sym)->function, Qunbound)) ? Qnil : Qt);
- }
-
- static void
- reject_constant_symbols (Lisp_Object sym, Lisp_Object newval, int function_p)
- {
- /* #### - I wonder if it would be better to just have a new magic value
- type and make nil, t, and all keywords have that same magic
- constant_symbol value. This test is awfully specific about what is
- constant and what isn't. --Stig */
- if (NILP (sym) || EQ (sym, Qt)
- #if 0
- /* #### - This is disabled until a new magic symbol_value for
- constants is added */
- || SYMBOL_IS_KEYWORD (sym)
- #endif
- )
- {
- signal_error (Qsetting_constant,
- ((EQ (newval, Qunbound))
- ? list1 (sym)
- : list2 (sym, newval)));
- }
-
- if (SYMBOL_VALUE_MAGIC_P (XSYMBOL (sym)->value) &&
- XSYMBOL_VALUE_MAGIC_TYPE (XSYMBOL (sym)->value) ==
- SYMVAL_CONST_SPECIFIER_FORWARD)
- signal_simple_error ("Use `set-specifier' to change a specifier's value",
- sym);
- }
-
- static void
- verify_ok_for_buffer_local (Lisp_Object sym)
- {
- if (NILP (sym) || EQ (sym, Qt)
- #if 0
- /* #### - This is disabled until a new magic symbol_value for
- constants is added */
- || SYMBOL_IS_KEYWORD (sym)
- #endif
- || (SYMBOL_VALUE_MAGIC_P (XSYMBOL (sym)->value) &&
- XSYMBOL_VALUE_MAGIC_TYPE (XSYMBOL (sym)->value) ==
- SYMVAL_DEFAULT_BUFFER_FORWARD)
- || (SYMBOL_VALUE_MAGIC_P (XSYMBOL (sym)->value) &&
- XSYMBOL_VALUE_MAGIC_TYPE (XSYMBOL (sym)->value) ==
- SYMVAL_CONST_SPECIFIER_FORWARD))
- signal_error (Qerror,
- list2 (build_string ("Symbol may not be buffer-local"),
- sym));
- }
-
- DEFUN ("makunbound", Fmakunbound, Smakunbound, 1, 1, 0,
- "Make SYMBOL's value be void.")
- (sym)
- Lisp_Object sym;
- {
- CHECK_SYMBOL (sym, 0);
- reject_constant_symbols (sym, Qunbound, 0);
- Fset (sym, Qunbound);
- return sym;
- }
-
- DEFUN ("fmakunbound", Ffmakunbound, Sfmakunbound, 1, 1, 0,
- "Make SYMBOL's function definition be void.")
- (sym)
- Lisp_Object sym;
- {
- CHECK_SYMBOL (sym, 0);
- reject_constant_symbols (sym, Qunbound, 1);
- XSYMBOL (sym)->function = Qunbound;
- return sym;
- }
-
- DEFUN ("symbol-function", Fsymbol_function, Ssymbol_function, 1, 1, 0,
- "Return SYMBOL's function definition. Error if that is void.")
- (symbol)
- Lisp_Object symbol;
- {
- CHECK_SYMBOL (symbol, 0);
- if (EQ (XSYMBOL (symbol)->function, Qunbound))
- return Fsignal (Qvoid_function, list1 (symbol));
- return XSYMBOL (symbol)->function;
- }
-
- DEFUN ("symbol-plist", Fsymbol_plist, Ssymbol_plist, 1, 1, 0,
- "Return SYMBOL's property list.")
- (sym)
- Lisp_Object sym;
- {
- CHECK_SYMBOL (sym, 0);
- return XSYMBOL (sym)->plist;
- }
-
- DEFUN ("symbol-name", Fsymbol_name, Ssymbol_name, 1, 1, 0,
- "Return SYMBOL's name, a string.")
- (sym)
- Lisp_Object sym;
- {
- Lisp_Object name;
-
- CHECK_SYMBOL (sym, 0);
- XSETSTRING (name, XSYMBOL (sym)->name);
- return name;
- }
-
- DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
- "Set SYMBOL's function definition to NEWVAL, and return NEWVAL.")
- (sym, newdef)
- Lisp_Object sym, newdef;
- {
- /* This function can GC */
- CHECK_SYMBOL (sym, 0);
- reject_constant_symbols (sym, newdef, 1);
- if (!NILP (Vautoload_queue) && !EQ (XSYMBOL (sym)->function, Qunbound))
- Vautoload_queue = Fcons (Fcons (sym, XSYMBOL (sym)->function),
- Vautoload_queue);
- XSYMBOL (sym)->function = newdef;
- /* Handle automatic advice activation */
- if (CONSP (XSYMBOL (sym)->plist) && !NILP (Fget (sym, Qad_advice_info,
- Qnil)))
- {
- call2 (Qad_activate, sym, Qnil);
- newdef = XSYMBOL (sym)->function;
- }
- return newdef;
- }
-
- /* FSFmacs */
- DEFUN ("define-function", Fdefine_function, Sdefine_function, 2, 2, 0,
- "Set SYMBOL's function definition to NEWVAL, and return NEWVAL.\n\
- Associates the function with the current load file, if any.")
- (sym, newdef)
- Lisp_Object sym, newdef;
- {
- /* This function can GC */
- CHECK_SYMBOL (sym, 0);
- Ffset (sym, newdef);
- LOADHIST_ATTACH (sym);
- return newdef;
- }
-
-
- DEFUN ("setplist", Fsetplist, Ssetplist, 2, 2, 0,
- "Set SYMBOL's property list to NEWVAL, and return NEWVAL.")
- (sym, newplist)
- Lisp_Object sym, newplist;
- {
- CHECK_SYMBOL (sym, 0);
- XSYMBOL (sym)->plist = newplist;
- return newplist;
- }
-
-
- /**********************************************************************/
- /* symbol-value */
- /**********************************************************************/
-
- /* If the contents of the value cell of a symbol is one of the following
- three types of objects, then the symbol is "magic" in that setting
- and retrieving its value doesn't just set or retrieve the raw
- contents of the value cell. None of these objects can escape to
- the user level, so there is no loss of generality.
-
- If a symbol is "unbound", then the contents of its value cell is
- Qunbound. Despite appearances, this is *not* a symbol, but is
- a symbol-value-forward object.
-
- Logically all of the following objects are "symbol-value-magic"
- objects, and there are some games played w.r.t. this (#### this
- should be cleaned up). SYMBOL_VALUE_MAGIC_P is true for all of
- the object types. XSYMBOL_VALUE_MAGIC_TYPE returns the type of
- symbol-value-magic object. There are more than three types
- returned by this macro: in particular, symbol-value-forward
- has six subtypes, and symbol-value-buffer-local has two. See
- symeval.h.
-
- symbol-value-forward is used for variables whose actual contents
- are stored in a C variable of some sort, and for Qunbound. The
- lcheader.next field (which is only used to chain together free
- lcrecords) holds a pointer to the actual C variable. Included
- in this type are "buffer-local" variables that are actually
- stored in the buffer object itself; in this case, the "pointer"
- is an offset into the struct buffer structure.
-
- symbol-value-buffer-local is used for variables that have had
- `make-local-variable' or `make-variable-buffer-local' applied
- to them. This object contains an alist mapping buffers to
- values. In addition, the object contains a "current value",
- which is the value in some buffer. Whenever you access the
- variable with `symbol-value' or set it with `set' or `setq',
- things are switched around so that the "current value"
- refers to the current buffer, if it wasn't already. This
- way, repeated references to a variable in the same buffer
- are almost as efficient as if the variable weren't buffer
- local. Note that the alist may not be up-to-date w.r.t.
- the buffer whose value is current, as the "current value"
- cache is normally only flushed into the alist when the
- buffer it refers to changes.
-
- Note also that it is possible for `make-local-variable'
- or `make-variable-buffer-local' to be called on a variable
- that forwards into a C variable (i.e. a variable whose
- value cell is a symbol-value-forward). In this case,
- the value cell becomes a symbol-value-buffer-local (as
- always), and the symbol-value-forward moves into
- the "current value" cell in this object. Also, in
- this case the "current value" *always* refers to the
- current buffer, so that the values of the C variable
- always is the correct value for the current buffer.
- set_buffer_internal() automatically updates the current-value
- cells of all buffer-local variables that forward into C
- variables. (There is a list of all buffer-local variables
- that is maintained for this and other purposes.)
-
- A symbol-value-varalias object is used for variables that
- are aliases for other variables. This object contains
- the symbol that this variable is aliased to.
- symbol-value-varalias objects cannot occur anywhere within
- a symbol-value-buffer-local object, and most of the
- low-level functions below do not accept them; you need
- to call follow_varalias_pointers to get the actual
- symbol to operate on.
- */
-
- static Lisp_Object mark_symbol_value_buffer_local (Lisp_Object,
- void (*) (Lisp_Object));
- static Lisp_Object mark_symbol_value_varalias (Lisp_Object,
- void (*) (Lisp_Object));
-
- DEFINE_LRECORD_IMPLEMENTATION ("symbol-value-forward",
- symbol_value_forward,
- this_one_is_unmarkable,
- print_symbol_value_magic, 0, 0, 0,
- struct symbol_value_forward);
-
- DEFINE_LRECORD_IMPLEMENTATION ("symbol-value-buffer-local",
- symbol_value_buffer_local,
- mark_symbol_value_buffer_local,
- print_symbol_value_magic,
- 0, 0, 0,
- struct symbol_value_buffer_local);
-
- DEFINE_LRECORD_IMPLEMENTATION ("symbol-value-varalias",
- symbol_value_varalias,
- mark_symbol_value_varalias,
- print_symbol_value_magic,
- 0, 0, 0,
- struct symbol_value_varalias);
-
- static Lisp_Object
- mark_symbol_value_buffer_local (Lisp_Object obj,
- void (*markobj) (Lisp_Object))
- {
- struct symbol_value_buffer_local *bfwd;
-
- assert (XSYMBOL_VALUE_MAGIC_TYPE (obj) == SYMVAL_BUFFER_LOCAL ||
- XSYMBOL_VALUE_MAGIC_TYPE (obj) == SYMVAL_SOME_BUFFER_LOCAL);
-
- bfwd = XSYMBOL_VALUE_BUFFER_LOCAL (obj);
- ((markobj) (bfwd->default_value));
- ((markobj) (bfwd->current_value));
- ((markobj) (bfwd->current_buffer));
- return (bfwd->current_alist_element);
- }
-
- static Lisp_Object
- mark_symbol_value_varalias (Lisp_Object obj,
- void (*markobj) (Lisp_Object))
- {
- struct symbol_value_varalias *bfwd;
-
- assert (XSYMBOL_VALUE_MAGIC_TYPE (obj) == SYMVAL_VARALIAS);
-
- bfwd = XSYMBOL_VALUE_VARALIAS (obj);
- ((markobj) (bfwd->shadowed));
- return (bfwd->aliasee);
- }
-
- /* Should never, ever be called. (except by an external debugger) */
- void
- print_symbol_value_magic (Lisp_Object obj,
- Lisp_Object printcharfun, int escapeflag)
- {
- char buf[200];
- sprintf (buf, "#<INTERNAL EMACS BUG (symfwd %d) 0x%x>",
- (LISP_WORD_TYPE) XSYMBOL_VALUE_MAGIC_TYPE (obj),
- (LISP_WORD_TYPE) XPNTR (obj));
- write_c_string (buf, printcharfun);
- }
-
-
- /* Getting and setting values of symbols */
-
- /* Given the raw contents of a symbol value cell, return the Lisp value of
- the symbol. The raw contents cannot be a symbol-value-buffer-local or
- symbol-value-varalias; use other functions for that.
- */
-
- static Lisp_Object
- do_symval_forwarding (Lisp_Object valcontents, struct buffer *buffer)
- {
- CONST struct symbol_value_forward *fwd;
-
- if (!SYMBOL_VALUE_MAGIC_P (valcontents))
- return (valcontents);
-
- fwd = XSYMBOL_VALUE_FORWARD (valcontents);
- switch (fwd->magic.type)
- {
- case SYMVAL_FIXNUM_FORWARD:
- return (make_number (*((int *)symbol_value_forward_forward (fwd))));
-
- case SYMVAL_BOOLEAN_FORWARD:
- {
- if (*((int *)symbol_value_forward_forward (fwd)))
- return (Qt);
- else
- return (Qnil);
- }
-
- case SYMVAL_OBJECT_FORWARD:
- case SYMVAL_CONST_SPECIFIER_FORWARD:
- return (*((Lisp_Object *)symbol_value_forward_forward (fwd)));
-
- case SYMVAL_DEFAULT_BUFFER_FORWARD:
- return (*((Lisp_Object *)((char *) XBUFFER (Vbuffer_defaults)
- + ((char *)symbol_value_forward_forward (fwd)
- - (char *)&buffer_local_flags))));
-
-
- case SYMVAL_CURRENT_BUFFER_FORWARD:
- return (*((Lisp_Object *)((char *)buffer
- + ((char *)symbol_value_forward_forward (fwd)
- - (char *)&buffer_local_flags))));
-
- case SYMVAL_UNBOUND_MARKER:
- return (valcontents);
-
- #ifdef LISP_MAGIC
- case SYMVAL_LISP_MAGIC:
- #endif
-
- default:
- abort ();
- }
- return Qnil; /* suppress compiler warning */
- }
-
- static void
- set_default_buffer_slot_variable (Lisp_Object sym,
- Lisp_Object value)
- {
- /* Handle variables like case-fold-search that have special slots in
- the buffer. Make them work apparently like buffer_local variables.
- */
- Lisp_Object valcontents = XSYMBOL (sym)->value;
- CONST struct symbol_value_forward *fwd
- = XSYMBOL_VALUE_FORWARD (valcontents);
- int offset = ((char *) symbol_value_forward_forward (fwd)
- - (char *) &buffer_local_flags);
- int mask = XINT (*((Lisp_Object *) symbol_value_forward_forward (fwd)));
- int (*magicfun) (Lisp_Object sym, Lisp_Object *val, struct buffer *buf,
- int flags) = symbol_value_forward_magicfun (fwd);
-
- *((Lisp_Object *) (offset + (char *) XBUFFER (Vbuffer_defaults)))
- = value;
-
- if (mask > 0) /* Not always per-buffer */
- {
- Lisp_Object tail;
-
- /* Set value in each buffer which hasn't shadowed the default */
- LIST_LOOP (tail, Vbuffer_alist)
- {
- struct buffer *b = XBUFFER (XCDR (XCAR (tail)));
- if (!(b->local_var_flags & mask))
- {
- if (magicfun)
- (magicfun) (sym, &value, b, 0);
- *((Lisp_Object *) (offset + (char *) b)) = value;
- }
- }
- }
- }
-
- /* Store NEWVAL into SYM. If SYM is a symbol-value-buffer-local,
- OVALUE should be the contents of the current-value cell in the
- buffer-local structure; otherwise, ovalue should be the actual
- contents of the value cell of SYM. If SYM is a
- symbol-value-buffer-local, this function will only modify its
- current-value cell, which should already be set up to point to
- the current buffer. SYM may not be a symbol-value-varalias
- or an unsettable symbol.
- */
-
- static void
- store_symval_forwarding (Lisp_Object sym, Lisp_Object ovalue,
- Lisp_Object newval)
- {
- if (!SYMBOL_VALUE_MAGIC_P (ovalue) || EQ (ovalue, Qunbound))
- {
- ovalue = XSYMBOL (sym)->value;
-
- if (!SYMBOL_VALUE_MAGIC_P (ovalue))
- {
- XSYMBOL (sym)->value = newval;
- }
-
- else switch (XSYMBOL_VALUE_MAGIC_TYPE (ovalue))
- {
- case SYMVAL_BUFFER_LOCAL:
- case SYMVAL_SOME_BUFFER_LOCAL:
- XSYMBOL_VALUE_BUFFER_LOCAL (ovalue)->current_value = newval;
- break;
- default:
- XSYMBOL (sym)->value = newval;
- break;
- }
- return;
- }
-
- else
- {
- CONST struct symbol_value_forward *fwd
- = XSYMBOL_VALUE_FORWARD (ovalue);
- int type = XSYMBOL_VALUE_MAGIC_TYPE (ovalue);
- int (*magicfun) (Lisp_Object sym, Lisp_Object *val, struct buffer *buf,
- int flags) = symbol_value_forward_magicfun (fwd);
-
- switch (type)
- {
- case SYMVAL_FIXNUM_FORWARD:
- {
- CHECK_INT (newval, 1);
- if (magicfun)
- (magicfun) (sym, &newval, 0, 0);
- *((int *) symbol_value_forward_forward (fwd)) = XINT (newval);
- return;
- }
-
- case SYMVAL_BOOLEAN_FORWARD:
- {
- if (magicfun)
- (magicfun) (sym, &newval, 0, 0);
- *((int *) symbol_value_forward_forward (fwd))
- = ((NILP (newval)) ? 0 : 1);
- return;
- }
-
- case SYMVAL_OBJECT_FORWARD:
- {
- if (magicfun)
- (magicfun) (sym, &newval, 0, 0);
- *((Lisp_Object *) symbol_value_forward_forward (fwd)) = newval;
- return;
- }
-
- case SYMVAL_DEFAULT_BUFFER_FORWARD:
- {
- set_default_buffer_slot_variable (sym, newval);
- return;
- }
-
- case SYMVAL_CURRENT_BUFFER_FORWARD:
- {
- if (magicfun)
- (magicfun) (sym, &newval, current_buffer, 0);
- *((Lisp_Object *) ((char *) current_buffer
- + ((char *) symbol_value_forward_forward (fwd)
- - (char *) &buffer_local_flags)))
- = newval;
- return;
- }
-
- default:
- abort ();
- }
- }
- }
-
- static Lisp_Object
- buffer_local_alist_element (struct buffer *buffer, Lisp_Object symbol,
- struct symbol_value_buffer_local *bfwd)
- {
- if (!NILP (bfwd->current_buffer) &&
- XBUFFER (bfwd->current_buffer) == buffer)
- /* This is just an optimization of the below. */
- return (bfwd->current_alist_element);
- else
- return (assq_no_quit (symbol, buffer->local_var_alist));
- }
-
-
- static Lisp_Object
- swap_in_symval_forwarding_1 (Lisp_Object symbol,
- struct symbol_value_buffer_local *bfwd)
- {
- Lisp_Object cval = do_symval_forwarding (bfwd->current_value,
- /* was current_buffer */
- NILP (bfwd->current_buffer) ?
- 0 : XBUFFER (bfwd->current_buffer));
- if (NILP (bfwd->current_alist_element))
- /* current_value may be updated more recently than default_value */
- bfwd->default_value = cval;
- else
- Fsetcdr (bfwd->current_alist_element, cval);
-
- return (buffer_local_alist_element (current_buffer, symbol, bfwd));
- }
-
-
- /* Set up the buffer-local symbol SYM for validity in the current
- buffer. BFWD is the contents of its value cell.
- Return the new contents of the current-value cell (this will be
- a symbol-value-forward or a non-magic object). */
-
- static Lisp_Object
- swap_in_symval_forwarding (Lisp_Object sym,
- struct symbol_value_buffer_local *bfwd)
- {
- /* If the current buffer is not BUFFER,
- we store the current CURRENT-VALUE value into CURRENT-ALIST-ELEMENT,
- then find the appropriate alist element for the buffer now current
- and set up CURRENT-ALIST-ELEMENT.
- Then we set CURRENT-VALUE out of that element, and store into BUFFER.
- Note that CURRENT-VALUE can be a forwarding pointer. */
- if (NILP (bfwd->current_buffer) ||
- current_buffer != XBUFFER (bfwd->current_buffer))
- {
- Lisp_Object tem = swap_in_symval_forwarding_1 (sym, bfwd);
- if (NILP (tem))
- {
- bfwd->current_alist_element = Qnil;
- tem = bfwd->default_value;
- }
- else
- {
- bfwd->current_alist_element = tem;
- tem = Fcdr (tem);
- }
- XSETBUFFER (bfwd->current_buffer, current_buffer);
- store_symval_forwarding (sym,
- bfwd->current_value,
- tem);
- }
- return (bfwd->current_value);
- }
-
- /* Follow the chain of variable aliases for OBJECT. Return the resulting
- symbol, whose value cell is guaranteed not to be a symbol-value-varalias. */
-
- static Lisp_Object
- follow_varalias_pointers (Lisp_Object object)
- {
- Lisp_Object tortoise = object;
- Lisp_Object hare = object;
-
- /* based off of indirect_function() */
- for (;;)
- {
- Lisp_Object value;
-
- value = XSYMBOL (hare)->value;
- if (!SYMBOL_VALUE_VARALIAS_P (value))
- break;
- hare = symbol_value_varalias_aliasee (XSYMBOL_VALUE_VARALIAS (value));
- value = XSYMBOL (hare)->value;
- if (!SYMBOL_VALUE_VARALIAS_P (value))
- break;
- hare = symbol_value_varalias_aliasee (XSYMBOL_VALUE_VARALIAS (value));
-
- tortoise = symbol_value_varalias_aliasee
- (XSYMBOL_VALUE_VARALIAS (XSYMBOL (tortoise)->value));
-
- if (EQ (hare, tortoise))
- return (Fsignal (Qcyclic_variable_indirection, list1 (object)));
- }
-
- return hare;
- }
-
-
- void
- kill_buffer_local_variables (struct buffer *buf)
- {
- Lisp_Object prev;
- Lisp_Object alist;
-
- /* Any which are supposed to be permanent,
- make local again, with the same values they had. */
-
- for (prev = Qnil, alist = buf->local_var_alist;
- !NILP (alist);
- prev = alist, alist = XCDR (alist))
- {
- Lisp_Object sym = XCAR (XCAR (alist));
- struct symbol_value_buffer_local *bfwd;
-
- if (!SYMBOL_VALUE_MAGIC_P (XSYMBOL (sym)->value))
- abort ();
-
- bfwd = XSYMBOL_VALUE_BUFFER_LOCAL (XSYMBOL (sym)->value);
- if (bfwd->magic.type != SYMVAL_BUFFER_LOCAL
- && bfwd->magic.type != SYMVAL_SOME_BUFFER_LOCAL)
- abort ();
-
- if (NILP (Fget (sym, Qpermanent_local, Qnil)))
- {
- /* Really truly kill it. */
- if (!NILP (prev))
- XCDR (prev) = XCDR (alist);
- else
- current_buffer->local_var_alist = XCDR (alist);
-
- if (!NILP (bfwd->current_buffer) &&
- buf == XBUFFER (bfwd->current_buffer))
- bfwd->current_buffer = Qnil;
-
- /* In case it's a C variable, flush it out. */
- swap_in_symval_forwarding (sym, bfwd);
- }
- }
- }
-
- /* Find the value of a symbol, returning Qunbound if it's not bound.
- Note that it must not be possible to QUIT within this function. */
-
- Lisp_Object
- symbol_value_in_buffer (Lisp_Object sym, Lisp_Object buffer)
- {
- Lisp_Object valcontents;
- struct buffer *buf;
-
- CHECK_SYMBOL (sym, 0);
-
- retry:
- CHECK_BUFFER (buffer, 1);
- valcontents = XSYMBOL (sym)->value;
- buf = XBUFFER (buffer);
-
- if (!SYMBOL_VALUE_MAGIC_P (valcontents))
- return (valcontents);
-
- switch (XSYMBOL_VALUE_MAGIC_TYPE (valcontents))
- {
- case SYMVAL_VARALIAS:
- sym = follow_varalias_pointers (sym);
- /* presto change-o! */
- goto retry;
-
- case SYMVAL_BUFFER_LOCAL:
- case SYMVAL_SOME_BUFFER_LOCAL:
- {
- struct symbol_value_buffer_local *bfwd
- = XSYMBOL_VALUE_BUFFER_LOCAL (valcontents);
-
- if (!NILP (bfwd->current_buffer) &&
- buf == XBUFFER (bfwd->current_buffer))
- valcontents = bfwd->current_value;
- else
- {
- valcontents = assq_no_quit (sym, buf->local_var_alist);
- if (NILP (valcontents))
- valcontents = bfwd->default_value;
- else
- valcontents = Fcdr (valcontents);
- }
- break;
- }
-
- default:
- break;
- }
- return (do_symval_forwarding (valcontents, buf));
- }
-
- Lisp_Object
- find_symbol_value (Lisp_Object sym)
- {
- Lisp_Object valcontents;
-
- CHECK_SYMBOL (sym, 0);
-
- retry:
- valcontents = XSYMBOL (sym)->value;
-
- if (!SYMBOL_VALUE_MAGIC_P (valcontents))
- return (valcontents);
-
- switch (XSYMBOL_VALUE_MAGIC_TYPE (valcontents))
- {
- case SYMVAL_VARALIAS:
- sym = follow_varalias_pointers (sym);
- /* presto change-o! */
- goto retry;
-
- case SYMVAL_BUFFER_LOCAL:
- case SYMVAL_SOME_BUFFER_LOCAL:
- {
- struct symbol_value_buffer_local *bfwd
- = XSYMBOL_VALUE_BUFFER_LOCAL (valcontents);
- valcontents = swap_in_symval_forwarding (sym, bfwd);
- break;
- }
- default:
- break;
- }
-
- return do_symval_forwarding (valcontents, current_buffer);
- }
-
- DEFUN ("symbol-value", Fsymbol_value, Ssymbol_value, 1, 1, 0,
- "Return SYMBOL's value. Error if that is void.")
- (sym)
- Lisp_Object sym;
- {
- Lisp_Object val = find_symbol_value (sym);
-
- if (EQ (val, Qunbound))
- return Fsignal (Qvoid_variable, list1 (sym));
- else
- return val;
- }
-
- DEFUN ("set", Fset, Sset, 2, 2, 0,
- "Set SYMBOL's value to NEWVAL, and return NEWVAL.")
- (sym, newval)
- Lisp_Object sym, newval;
- {
- REGISTER Lisp_Object valcontents;
-
- CHECK_SYMBOL (sym, 0);
-
- retry:
- reject_constant_symbols (sym, newval, 0);
- valcontents = XSYMBOL (sym)->value;
-
- if (SYMBOL_VALUE_MAGIC_P (valcontents))
- {
- switch (XSYMBOL_VALUE_MAGIC_TYPE (valcontents))
- {
- case SYMVAL_VARALIAS:
- sym = follow_varalias_pointers (sym);
- /* presto change-o! */
- goto retry;
-
- case SYMVAL_FIXNUM_FORWARD:
- case SYMVAL_BOOLEAN_FORWARD:
- case SYMVAL_OBJECT_FORWARD:
- case SYMVAL_DEFAULT_BUFFER_FORWARD:
- if (EQ (newval, Qunbound))
- signal_error (Qerror,
- list2 (build_string ("Cannot makunbound"), sym));
- break;
-
- case SYMVAL_UNBOUND_MARKER:
- break;
-
- case SYMVAL_CURRENT_BUFFER_FORWARD:
- {
- CONST struct symbol_value_forward *fwd
- = XSYMBOL_VALUE_FORWARD (valcontents);
- int mask = XINT (*((Lisp_Object *)
- symbol_value_forward_forward (fwd)));
- if (mask > 0)
- /* Setting this variable makes it buffer-local */
- current_buffer->local_var_flags |= mask;
- break;
- }
-
- case SYMVAL_BUFFER_LOCAL:
- case SYMVAL_SOME_BUFFER_LOCAL:
- {
- /* If we want to examine or set the value and BUFFER is current,
- we just examine or set CURRENT-VALUE. If BUFFER is not current,
- we store the current CURRENT-VALUE value into CURRENT-ALIST-
- ELEMENT, then find the appropriate alist element for the buffer
- now current and set up CURRENT-ALIST-ELEMENT. Then we set
- CURRENT-VALUE out of that element, and store into BUFFER.
-
- If we are setting the variable and the current buffer does
- not have an alist entry for this variable, an alist entry is
- created.
-
- Note that CURRENT-VALUE can be a forwarding pointer. Each time
- it is examined or set, forwarding must be done.
- */
- struct symbol_value_buffer_local *bfwd
- = XSYMBOL_VALUE_BUFFER_LOCAL (valcontents);
- int some_buffer_local_p =
- (bfwd->magic.type == SYMVAL_SOME_BUFFER_LOCAL);
- /* What value are we caching right now? */
- Lisp_Object aelt = bfwd->current_alist_element;
-
- if (!NILP (bfwd->current_buffer) &&
- current_buffer == XBUFFER (bfwd->current_buffer)
- && ((some_buffer_local_p)
- ? 1 /* doesn't automatically become local */
- : !NILP (aelt) /* already local */
- ))
- {
- /* Cache is valid */
- valcontents = bfwd->current_value;
- }
- else
- {
- /* If the current buffer is not the buffer whose binding is
- currently cached, or if it's a SYMVAL_BUFFER_LOCAL and
- we're looking at the default value, the cache is invalid; we
- need to write it out, and find the new CURRENT-ALIST-ELEMENT
- */
-
- /* Write out the cached value for the old buffer; copy it
- back to its alist element. This works if the current
- buffer only sees the default value, too. */
- /* Find the new value for CURRENT-ALIST-ELEMENT. */
- aelt = swap_in_symval_forwarding_1 (sym, bfwd);
- if (NILP (aelt))
- {
- /* This buffer is still seeing the default value. */
- if (!some_buffer_local_p)
- {
- /* If it's a SYMVAL_BUFFER_LOCAL, give this buffer a
- new assoc for a local value and set
- CURRENT-ALIST-ELEMENT to point to that. */
- aelt = do_symval_forwarding (bfwd->current_value,
- current_buffer);
- aelt = Fcons (sym, aelt);
- current_buffer->local_var_alist
- = Fcons (aelt, current_buffer->local_var_alist);
- }
- else
- {
- /* If the variable is a SYMVAL_SOME_BUFFER_LOCAL,
- we're currently seeing the default value. */
- ;
- }
- }
- /* Cache the new buffer's assoc in CURRENT-ALIST-ELEMENT. */
- bfwd->current_alist_element = aelt;
- /* Set BUFFER, now that CURRENT-ALIST-ELEMENT is accurate. */
- XSETBUFFER (bfwd->current_buffer, current_buffer);
- valcontents = bfwd->current_value;
- }
- break;
- }
- default:
- abort ();
- }
- }
- store_symval_forwarding (sym, valcontents, newval);
-
- return (newval);
- }
-
-
- /* Access or set a buffer-local symbol's default value. */
-
- /* Return the default value of SYM, but don't check for voidness.
- Return Qunbound if it is void. */
-
- static Lisp_Object
- default_value (Lisp_Object sym)
- {
- Lisp_Object valcontents;
-
- CHECK_SYMBOL (sym, 0);
-
- retry:
- valcontents = XSYMBOL (sym)->value;
-
- if (!SYMBOL_VALUE_MAGIC_P (valcontents))
- return (valcontents);
-
- switch (XSYMBOL_VALUE_MAGIC_TYPE (valcontents))
- {
- case SYMVAL_VARALIAS:
- sym = follow_varalias_pointers (sym);
- /* presto change-o! */
- goto retry;
-
- case SYMVAL_UNBOUND_MARKER:
- return valcontents;
-
- case SYMVAL_CURRENT_BUFFER_FORWARD:
- {
- CONST struct symbol_value_forward *fwd
- = XSYMBOL_VALUE_FORWARD (valcontents);
- return (*((Lisp_Object *)((char *) XBUFFER (Vbuffer_defaults)
- + ((char *)symbol_value_forward_forward (fwd)
- - (char *)&buffer_local_flags))));
- }
- case SYMVAL_BUFFER_LOCAL:
- case SYMVAL_SOME_BUFFER_LOCAL:
- {
- struct symbol_value_buffer_local *bfwd =
- XSYMBOL_VALUE_BUFFER_LOCAL (valcontents);
-
- /* Handle user-created local variables. */
- /* If var is set up for a buffer that lacks a local value for it,
- the current value is nominally the default value.
- But the current value slot may be more up to date, since
- ordinary setq stores just that slot. So use that. */
- if (NILP (bfwd->current_alist_element))
- return (do_symval_forwarding (bfwd->current_value, current_buffer));
- else
- return (bfwd->default_value);
- }
- default:
- /* For other variables, get the current value. */
- return (do_symval_forwarding (valcontents, current_buffer));
- }
- return Qnil; /* suppress compiler warning */
- }
-
- DEFUN ("default-boundp", Fdefault_boundp, Sdefault_boundp, 1, 1, 0,
- "Return T if SYMBOL has a non-void default value.\n\
- This is the value that is seen in buffers that do not have their own values\n\
- for this variable.")
- (sym)
- Lisp_Object sym;
- {
- Lisp_Object value;
-
- value = default_value (sym);
- return (EQ (value, Qunbound) ? Qnil : Qt);
- }
-
- DEFUN ("default-value", Fdefault_value, Sdefault_value, 1, 1, 0,
- "Return SYMBOL's default value.\n\
- This is the value that is seen in buffers that do not have their own values\n\
- for this variable. The default value is meaningful for variables with\n\
- local bindings in certain buffers.")
- (sym)
- Lisp_Object sym;
- {
- Lisp_Object value;
-
- value = default_value (sym);
- if (EQ (value, Qunbound))
- return Fsignal (Qvoid_variable, list1 (sym));
- return value;
- }
-
- DEFUN ("set-default", Fset_default, Sset_default, 2, 2, 0,
- "Set SYMBOL's default value to VAL. SYMBOL and VAL are evaluated.\n\
- The default value is seen in buffers that do not have their own values\n\
- for this variable.")
- (sym, value)
- Lisp_Object sym, value;
- {
- Lisp_Object valcontents;
-
- CHECK_SYMBOL (sym, 0);
-
- retry:
- valcontents = XSYMBOL (sym)->value;
-
- if (!SYMBOL_VALUE_MAGIC_P (valcontents))
- return Fset (sym, value);
-
- switch (XSYMBOL_VALUE_MAGIC_TYPE (valcontents))
- {
- case SYMVAL_VARALIAS:
- sym = follow_varalias_pointers (sym);
- /* presto change-o! */
- goto retry;
-
- case SYMVAL_CURRENT_BUFFER_FORWARD:
- set_default_buffer_slot_variable (sym, value);
- return (value);
-
- case SYMVAL_BUFFER_LOCAL:
- case SYMVAL_SOME_BUFFER_LOCAL:
- {
- /* Store new value into the DEFAULT-VALUE slot */
- struct symbol_value_buffer_local *bfwd
- = XSYMBOL_VALUE_BUFFER_LOCAL (valcontents);
-
- bfwd->default_value = value;
- /* If current-buffer doesn't shadow default_value,
- * we must set the CURRENT-VALUE slot too */
- if (NILP (bfwd->current_alist_element))
- store_symval_forwarding (sym, bfwd->current_value, value);
- return (value);
- }
-
- default:
- return Fset (sym, value);
- }
- return Qnil; /* suppress compiler warning */
- }
-
- DEFUN ("setq-default", Fsetq_default, Ssetq_default, 2, UNEVALLED, 0,
- "Set the default value of variable VAR to VALUE.\n\
- VAR, the variable name, is literal (not evaluated);\n\
- VALUE is an expression and it is evaluated.\n\
- The default value of a variable is seen in buffers\n\
- that do not have their own values for the variable.\n\
- \n\
- More generally, you can use multiple variables and values, as in\n\
- (setq-default SYM VALUE SYM VALUE...)\n\
- This sets each SYM's default value to the corresponding VALUE.\n\
- The VALUE for the Nth SYM can refer to the new default values\n\
- of previous SYMs.")
- (args)
- Lisp_Object args;
- {
- /* This function can GC */
- Lisp_Object args_left;
- Lisp_Object val, sym;
- struct gcpro gcpro1;
-
- if (NILP (args))
- return Qnil;
-
- args_left = args;
- GCPRO1 (args);
-
- do
- {
- val = Feval (Fcar (Fcdr (args_left)));
- sym = Fcar (args_left);
- Fset_default (sym, val);
- args_left = Fcdr (Fcdr (args_left));
- }
- while (!NILP (args_left));
-
- UNGCPRO;
- return val;
- }
-
- /* Lisp functions for creating and removing buffer-local variables. */
-
- DEFUN ("make-variable-buffer-local", Fmake_variable_buffer_local,
- Smake_variable_buffer_local,
- 1, 1, "vMake Variable Buffer Local: ",
- "Make VARIABLE have a separate value for each buffer.\n\
- At any time, the value for the current buffer is in effect.\n\
- There is also a default value which is seen in any buffer which has not yet\n\
- set its own value.\n\
- Using `set' or `setq' to set the variable causes it to have a separate value\n\
- for the current buffer if it was previously using the default value.\n\
- The function `default-value' gets the default value and `set-default'\n\
- sets it.")
- (variable)
- Lisp_Object variable;
- {
- Lisp_Object valcontents;
-
- CHECK_SYMBOL (variable, 0);
-
- retry:
- verify_ok_for_buffer_local (variable);
-
- valcontents = XSYMBOL (variable)->value;
-
- if (SYMBOL_VALUE_MAGIC_P (valcontents))
- {
- switch (XSYMBOL_VALUE_MAGIC_TYPE (valcontents))
- {
- case SYMVAL_VARALIAS:
- variable = follow_varalias_pointers (variable);
- /* presto change-o! */
- goto retry;
-
- case SYMVAL_FIXNUM_FORWARD:
- case SYMVAL_BOOLEAN_FORWARD:
- case SYMVAL_OBJECT_FORWARD:
- case SYMVAL_UNBOUND_MARKER:
- break;
-
- case SYMVAL_CURRENT_BUFFER_FORWARD:
- case SYMVAL_BUFFER_LOCAL:
- /* Already per-each-buffer */
- return (variable);
-
- case SYMVAL_SOME_BUFFER_LOCAL:
- /* Transmogrify */
- XSYMBOL_VALUE_BUFFER_LOCAL (valcontents)->magic.type =
- SYMVAL_BUFFER_LOCAL;
- return (variable);
-
- default:
- abort ();
- }
- }
-
- {
- struct symbol_value_buffer_local *bfwd
- = alloc_lcrecord (sizeof (struct symbol_value_buffer_local),
- lrecord_symbol_value_buffer_local);
- bfwd->magic.type = SYMVAL_BUFFER_LOCAL;
-
- bfwd->default_value = find_symbol_value (variable);
- bfwd->current_value = valcontents;
- bfwd->current_alist_element = Qnil;
- bfwd->current_buffer = Fcurrent_buffer ();
- XSETSYMBOL_VALUE_MAGIC (XSYMBOL (variable)->value, bfwd);
- #if 1 /* #### Yuck! FSFmacs bug-compatibility*/
- /* This sets the default-value of any make-variable-buffer-local to nil.
- That just sucks. User can just use setq-default to effect that,
- but there's no way to do makunbound-default to undo this lossage. */
- if (EQ (valcontents, Qunbound))
- bfwd->default_value = Qnil;
- #endif
- #if 0 /* #### Yuck! */
- /* This sets the value to nil in this buffer.
- User could use (setq variable nil) to do this.
- It isn't as egregious to do this automatically
- as it is to do so to the default-value, but it's
- still really dubious. */
- if (EQ (valcontents, Qunbound))
- Fset (variable, Qnil);
- #endif
- return (variable);
- }
- }
-
- DEFUN ("make-local-variable", Fmake_local_variable, Smake_local_variable,
- 1, 1, "vMake Local Variable: ",
- "Make VARIABLE have a separate value in the current buffer.\n\
- Other buffers will continue to share a common default value.\n\
- (The buffer-local value of VARIABLE starts out as the same value\n\
- VARIABLE previously had. If VARIABLE was void, it remains void.)\n\
- See also `make-variable-buffer-local'.\n\
- \n\
- If the variable is already arranged to become local when set,\n\
- this function causes a local value to exist for this buffer,\n\
- just as if the variable were set.")
- (variable)
- Lisp_Object variable;
- {
- Lisp_Object valcontents;
- struct symbol_value_buffer_local *bfwd;
-
- CHECK_SYMBOL (variable, 0);
-
- retry:
- verify_ok_for_buffer_local (variable);
-
- valcontents = XSYMBOL (variable)->value;
-
- if (SYMBOL_VALUE_MAGIC_P (valcontents))
- {
- switch (XSYMBOL_VALUE_MAGIC_TYPE (valcontents))
- {
- case SYMVAL_VARALIAS:
- variable = follow_varalias_pointers (variable);
- /* presto change-o! */
- goto retry;
-
- case SYMVAL_FIXNUM_FORWARD:
- case SYMVAL_BOOLEAN_FORWARD:
- case SYMVAL_OBJECT_FORWARD:
- case SYMVAL_UNBOUND_MARKER:
- break;
-
- case SYMVAL_BUFFER_LOCAL:
- case SYMVAL_CURRENT_BUFFER_FORWARD:
- {
- /* Make sure the symbol has a local value in this particular
- buffer, by setting it to the same value it already has. */
- Fset (variable, find_symbol_value (variable));
- return (variable);
- }
-
- case SYMVAL_SOME_BUFFER_LOCAL:
- {
- if (!NILP (buffer_local_alist_element (current_buffer,
- variable,
- (XSYMBOL_VALUE_BUFFER_LOCAL
- (valcontents)))))
- goto already_local_to_current_buffer;
- else
- goto already_local_to_some_other_buffer;
- }
-
- default:
- abort ();
- }
- }
-
- /* Make sure variable is set up to hold per-buffer values */
- bfwd = alloc_lcrecord (sizeof (struct symbol_value_buffer_local),
- lrecord_symbol_value_buffer_local);
- bfwd->magic.type = SYMVAL_SOME_BUFFER_LOCAL;
-
- bfwd->current_buffer = Qnil;
- bfwd->current_alist_element = Qnil;
- bfwd->current_value = valcontents;
- bfwd->default_value = do_symval_forwarding (valcontents, current_buffer);
-
- #if 0
- if (EQ (bfwd->default_value, Qunbound))
- bfwd->default_value = Qnil; /* Yuck! */
- #endif
-
- XSETSYMBOL_VALUE_MAGIC (valcontents, bfwd);
- XSYMBOL (variable)->value = valcontents;
-
- already_local_to_some_other_buffer:
-
- /* Make sure this buffer has its own value of variable */
- bfwd = XSYMBOL_VALUE_BUFFER_LOCAL (valcontents);
-
- if (EQ (bfwd->default_value, Qunbound))
- {
- /* If default value is unbound, set local value to nil. */
- XSETBUFFER (bfwd->current_buffer, current_buffer);
- bfwd->current_alist_element = Fcons (variable, Qnil);
- current_buffer->local_var_alist = Fcons (bfwd->current_alist_element,
- current_buffer->local_var_alist);
- store_symval_forwarding (variable, bfwd->current_value, Qnil);
- return (variable);
- }
-
- current_buffer->local_var_alist
- = Fcons (Fcons (variable, bfwd->default_value),
- current_buffer->local_var_alist);
-
- /* Make sure symbol does not think it is set up for this buffer;
- force it to look once again for this buffer's value */
- if (!NILP (bfwd->current_buffer) &&
- current_buffer == XBUFFER (bfwd->current_buffer))
- bfwd->current_buffer = Qnil;
-
- already_local_to_current_buffer:
-
- /* If the symbol forwards into a C variable, then swap in the
- variable for this buffer immediately. If C code modifies the
- variable before we swap in, then that new value will clobber the
- default value the next time we swap. */
- bfwd = XSYMBOL_VALUE_BUFFER_LOCAL (valcontents);
- if (SYMBOL_VALUE_MAGIC_P (bfwd->current_value))
- {
- switch (XSYMBOL_VALUE_MAGIC_TYPE (bfwd->current_value))
- {
- case SYMVAL_FIXNUM_FORWARD:
- case SYMVAL_BOOLEAN_FORWARD:
- case SYMVAL_OBJECT_FORWARD:
- case SYMVAL_DEFAULT_BUFFER_FORWARD:
- swap_in_symval_forwarding (variable, bfwd);
- break;
-
- case SYMVAL_UNBOUND_MARKER:
- case SYMVAL_CURRENT_BUFFER_FORWARD:
- break;
-
- default:
- abort ();
- }
- }
-
- return (variable);
- }
-
- DEFUN ("kill-local-variable", Fkill_local_variable, Skill_local_variable,
- 1, 1, "vKill Local Variable: ",
- "Make VARIABLE no longer have a separate value in the current buffer.\n\
- From now on the default value will apply in this buffer.")
- (variable)
- Lisp_Object variable;
- {
- Lisp_Object valcontents;
-
- CHECK_SYMBOL (variable, 0);
-
- retry:
- valcontents = XSYMBOL (variable)->value;
-
- if (!SYMBOL_VALUE_MAGIC_P (valcontents))
- return (variable);
-
- switch (XSYMBOL_VALUE_MAGIC_TYPE (valcontents))
- {
- case SYMVAL_VARALIAS:
- variable = follow_varalias_pointers (variable);
- /* presto change-o! */
- goto retry;
-
- case SYMVAL_CURRENT_BUFFER_FORWARD:
- {
- CONST struct symbol_value_forward *fwd
- = XSYMBOL_VALUE_FORWARD (valcontents);
- int offset = ((char *) symbol_value_forward_forward (fwd)
- - (char *) &buffer_local_flags);
- int mask =
- XINT (*((Lisp_Object *) symbol_value_forward_forward (fwd)));
-
- if (mask > 0)
- {
- int (*magicfun) (Lisp_Object sym, Lisp_Object *val,
- struct buffer *buf, int flags) =
- symbol_value_forward_magicfun (fwd);
- Lisp_Object oldval = * (Lisp_Object *)
- (offset + (char *) XBUFFER (Vbuffer_defaults));
- if (magicfun)
- (magicfun) (variable, &oldval, current_buffer, 0);
- *(Lisp_Object *) (offset + (char *) current_buffer)
- = oldval;
- current_buffer->local_var_flags &= ~mask;
- }
- return (variable);
- }
-
- case SYMVAL_BUFFER_LOCAL:
- case SYMVAL_SOME_BUFFER_LOCAL:
- {
- /* Get rid of this buffer's alist element, if any */
- struct symbol_value_buffer_local *bfwd
- = XSYMBOL_VALUE_BUFFER_LOCAL (valcontents);
- Lisp_Object alist = current_buffer->local_var_alist;
- Lisp_Object alist_element
- = buffer_local_alist_element (current_buffer, variable, bfwd);
-
- if (!NILP (alist_element))
- current_buffer->local_var_alist = Fdelq (alist_element, alist);
-
- /* Make sure symbol does not think it is set up for this buffer;
- force it to look once again for this buffer's value */
- if (!NILP (bfwd->current_buffer) &&
- current_buffer == XBUFFER (bfwd->current_buffer))
- bfwd->current_buffer = Qnil;
-
- /* In case it's a C variable, flush it out. */
- swap_in_symval_forwarding (variable, bfwd);
- }
- return (variable);
-
- default:
- return (variable);
- }
- return Qnil; /* suppress compiler warning */
- }
-
- /* Used by specbind to determine what effects it might have. Returns:
- * 0 if symbol isn't buffer-local, and wouldn't be after it is set
- * <0 if symbol isn't presently buffer-local, but set would make it so
- * >0 if symbol is presently buffer-local
- */
- int
- symbol_value_buffer_local_info (Lisp_Object symbol, struct buffer *buffer)
- {
- Lisp_Object valcontents;
-
- retry:
- valcontents = XSYMBOL (symbol)->value;
-
- if (SYMBOL_VALUE_MAGIC_P (valcontents))
- {
- switch (XSYMBOL_VALUE_MAGIC_TYPE (valcontents))
- {
- case SYMVAL_VARALIAS:
- symbol = follow_varalias_pointers (symbol);
- /* presto change-o! */
- goto retry;
-
- case SYMVAL_CURRENT_BUFFER_FORWARD:
- {
- CONST struct symbol_value_forward *fwd
- = XSYMBOL_VALUE_FORWARD (valcontents);
- int mask = XINT (*((Lisp_Object *)
- symbol_value_forward_forward (fwd)));
- if ((mask <= 0) || (buffer && (buffer->local_var_flags & mask)))
- /* Already buffer-local */
- return (1);
- else
- /* Would be buffer-local after set */
- return (-1);
- }
- case SYMVAL_BUFFER_LOCAL:
- case SYMVAL_SOME_BUFFER_LOCAL:
- {
- struct symbol_value_buffer_local *bfwd
- = XSYMBOL_VALUE_BUFFER_LOCAL (valcontents);
- if (buffer
- && !NILP (buffer_local_alist_element (buffer, symbol, bfwd)))
- return (1);
- else
- return ((bfwd->magic.type == SYMVAL_BUFFER_LOCAL)
- ? -1 /* Automatically becomes local when set */
- : 0);
- }
- default:
- return (0);
- }
- }
- return (0);
- }
-
-
- DEFUN ("symbol-value-in-buffer", Fsymbol_value_in_buffer, Ssymbol_value_in_buffer, 3, 3, 0,
- "Return the value of SYMBOL in BUFFER, or UNBOUND-VALUE if it is unbound.")
- (symbol, buffer, unbound_value)
- Lisp_Object symbol, buffer, unbound_value;
- {
- Lisp_Object value;
- CHECK_SYMBOL (symbol, 0);
- CHECK_BUFFER (buffer, 0);
- value = symbol_value_in_buffer (symbol, buffer);
- if (EQ (value, Qunbound))
- return (unbound_value);
- else
- return (value);
- }
-
- DEFUN ("local-variable-p", Flocal_variable_p, Slocal_variable_p, 2, 3, 0,
- "Return t if SYMBOL's value is local to BUFFER.\n\
- If optional third arg AFTER-SET is true, return t if SYMBOL would be\n\
- buffer-local after it is set, regardless of whether it is so presently.")
- (symbol, buffer, after_set)
- Lisp_Object symbol, buffer, after_set;
- {
- int local_info;
-
- CHECK_SYMBOL (symbol, 0);
- if (!NILP (buffer))
- {
- buffer = get_buffer (buffer, 1);
- local_info = symbol_value_buffer_local_info (symbol, XBUFFER (buffer));
- }
- else
- {
- local_info = symbol_value_buffer_local_info (symbol, 0);
- }
-
- if (NILP (after_set))
- return ((local_info > 0) ? Qt : Qnil);
- else
- return ((local_info != 0) ? Qt : Qnil);
- }
-
-
- /* Lisp functions for working with variable aliases. */
-
- DEFUN ("defvaralias", Fdefvaralias, Sdefvaralias, 2, 2, 0,
- "Define a variable as an alias for another variable.\n\
- Thenceforth, any operations performed on VARIABLE will actually be\n\
- performed on ALIAS. Both VARIABLE and ALIAS should be symbols.\n\
- If ALIAS is nil, remove any aliases for VARIABLE.\n\
- ALIAS can itself be aliased, and the chain of variable aliases\n\
- will be followed appropriately.\n\
- If VARIABLE already has a value, this value will be shadowed\n\
- until the alias is removed, at which point it will be restored.\n\
- Currently VARIABLE cannot be a built-in variable, a variable that\n\
- has a buffer-local value in any buffer, or the symbols nil or t.")
- (variable, alias)
- Lisp_Object variable, alias;
- {
- struct symbol_value_varalias *bfwd;
- Lisp_Object valcontents;
-
- CHECK_SYMBOL (variable, 0);
- reject_constant_symbols (variable, Qunbound, 0);
-
- valcontents = XSYMBOL (variable)->value;
-
- if (NILP (alias))
- {
- if (SYMBOL_VALUE_VARALIAS_P (valcontents))
- {
- XSYMBOL (variable)->value =
- symbol_value_varalias_shadowed
- (XSYMBOL_VALUE_VARALIAS (valcontents));
- }
- return Qnil;
- }
-
- CHECK_SYMBOL (alias, 1);
- if (SYMBOL_VALUE_MAGIC_P (valcontents) && !EQ (valcontents, Qunbound))
- signal_simple_error ("Variable cannot be aliased", variable);
-
- bfwd = alloc_lcrecord (sizeof (struct symbol_value_varalias),
- lrecord_symbol_value_varalias);
- bfwd->magic.type = SYMVAL_VARALIAS;
- bfwd->aliasee = alias;
- bfwd->shadowed = valcontents;
-
- XSETSYMBOL_VALUE_MAGIC (valcontents, bfwd);
- XSYMBOL (variable)->value = valcontents;
- return Qnil;
- }
-
- DEFUN ("variable-alias", Fvariable_alias, Svariable_alias, 1, 1, 0,
- "If VARIABLE is aliased to another variable, return that variable.\n\
- VARIABLE should be a symbol. If VARIABLE is not aliased, return nil.\n\
- Variable aliases are created with `defvaralias'. See also\n\
- `indirect-variable'.")
- (variable)
- Lisp_Object variable;
- {
- Lisp_Object valcontents;
-
- CHECK_SYMBOL (variable, 0);
-
- valcontents = XSYMBOL (variable)->value;
-
- if (SYMBOL_VALUE_VARALIAS_P (valcontents))
- return symbol_value_varalias_aliasee
- (XSYMBOL_VALUE_VARALIAS (valcontents));
- else
- return Qnil;
- }
-
- DEFUN ("indirect-variable", Findirect_variable, Sindirect_variable, 1, 1, 0,
- "Return the variable at the end of OBJECT's variable-alias chain.\n\
- If OBJECT is a symbol, follow all variable aliases and return\n\
- the final (non-aliased) symbol. Variable aliases are created with\n\
- the function `defvaralias'.\n\
- If OBJECT is not a symbol, just return it.\n\
- Signal a cyclic-variable-indirection error if there is a loop in the\n\
- variable chain of symbols.")
- (object)
- Lisp_Object object;
- {
- if (!SYMBOLP (object))
- return object;
- return follow_varalias_pointers (object);
- }
-
-
- /************************************************************************/
- /* initialization */
- /************************************************************************/
-
- /* A dumped XEmacs image has a lot more than 1511 symbols. Last
- estimate was that there were actually around 6300. So let's try
- making this bigger and see if we get better hashing behavior. */
- #define OBARRAY_SIZE 16411
-
- #ifndef Qzero
- Lisp_Object Qzero;
- #endif
-
- /* some losing systems can't have static vars at function scope... */
- static struct symbol_value_magic guts_of_unbound_marker =
- { { { lrecord_symbol_value_forward }, 0, 69}, SYMVAL_UNBOUND_MARKER };
-
- void
- init_symbols_once_early (void)
- {
- Qnil = Fmake_symbol (make_pure_pname ((Bufbyte *) "nil", 3, 1));
- /* Bootstrapping problem: Qnil isn't set when make_pure_pname is
- called the first time. */
- XSYMBOL (Qnil)->name->plist = Qnil;
- XSYMBOL (Qnil)->value = Qnil; /* Nihil ex nihil */
- XSYMBOL (Qnil)->plist = Qnil;
-
- #ifndef Qzero
- Qzero = make_number (0); /* Only used if Lisp_Object is a union type */
- #endif
-
- Vobarray = make_vector (OBARRAY_SIZE, Qzero);
- initial_obarray = Vobarray;
- staticpro (&initial_obarray);
- /* Intern nil in the obarray */
- {
- /* These locals are to kludge around a pyramid compiler bug. */
- int hash;
- Lisp_Object *tem;
-
- hash = hash_string (string_data (XSYMBOL (Qnil)->name), 3);
- /* Separate statement here to avoid VAXC bug. */
- hash %= OBARRAY_SIZE;
- tem = &vector_data (XVECTOR (Vobarray))[hash];
- *tem = Qnil;
- }
-
- {
- /* Required to get around a GCC syntax error on certain
- architectures */
- struct symbol_value_magic *tem = &guts_of_unbound_marker;
-
- XSETSYMBOL_VALUE_MAGIC (Qunbound, tem);
- }
- if ((CONST void *) XPNTR (Qunbound) !=
- (CONST void *)&guts_of_unbound_marker)
- {
- /* This might happen on DATA_SEG_BITS machines. */
- /* abort (); */
- /* Can't represent a pointer to constant C data using a Lisp_Object.
- So heap-allocate it. */
- struct symbol_value_magic *urk = xmalloc (sizeof (*urk));
- memcpy (urk, &guts_of_unbound_marker, sizeof (*urk));
- XSETSYMBOL_VALUE_MAGIC (Qunbound, urk);
- }
-
- XSYMBOL (Qnil)->function = Qunbound;
-
- defsymbol (&Qt, "t");
- XSYMBOL (Qt)->value = Qt; /* Veritas aetera */
- Vquit_flag = Qnil;
- }
-
- void
- defsymbol (Lisp_Object *location, CONST char *name)
- {
- *location = Fintern (make_pure_pname ((Bufbyte *) name, strlen (name), 1),
- Qnil);
- staticpro (location);
- }
-
- void
- defkeyword (Lisp_Object *location, CONST char *name)
- {
- defsymbol (location, name);
- Fset (*location, *location);
- }
-
- void
- defsubr (struct Lisp_Subr *subr)
- {
- Lisp_Object sym = intern (subr_name (subr));
-
- /* Check that nobody spazzed */
- if (subr->max_args != MANY && subr->max_args != UNEVALLED)
- {
- if (subr->max_args > SUBR_MAX_ARGS /* Need to fix eval.c if so */
- || subr->max_args < subr->min_args)
- abort ();
- }
- if (subr->min_args < 0 || subr->min_args > SUBR_MAX_ARGS)
- abort ();
-
- if (!EQ (XSYMBOL (sym)->function, Qunbound)) abort ();
-
- XSETSUBR (XSYMBOL (sym)->function, subr);
- }
-
- void
- deferror (Lisp_Object *symbol, CONST char *name, CONST char *message,
- int error_type)
- {
- defsymbol (symbol, name);
- /* There should probably be a better way of dealing with this. */
- pure_put (*symbol, Qerror_conditions,
- error_type == 0 ? list1 (*symbol) :
- error_type == 1 ? list2 (*symbol, Qerror) :
- error_type == 2 ? list3 (*symbol, Qarith_error, Qerror) :
- error_type == 3 ? list4 (*symbol, Qdomain_error, Qarith_error,
- Qerror) :
- error_type == 4 ? list3 (*symbol, Qfile_error, Qerror) :
- (abort (), Qnil));
- /* NOT build_translated_string (). This function is called at load time
- and the string needs to get translated at run time. (This happens
- in the function (display-error) in cmdloop.el.) */
- pure_put (*symbol, Qerror_message, build_string (message));
- }
-
- void
- syms_of_symbols (void)
- {
- /* some basic symbols used in Ffset and such */
- defsymbol (&Qvariable_documentation, "variable-documentation");
- defsymbol (&Qvariable_domain, "variable-domain"); /* I18N3 */
- defsymbol (&Qad_advice_info, "ad-advice-info");
- defsymbol (&Qad_activate, "ad-activate");
-
- defsubr (&Sintern);
- defsubr (&Sintern_soft);
- defsubr (&Smapatoms);
- defsubr (&Sapropos_internal);
-
- defsubr (&Ssymbol_function);
- defsubr (&Ssymbol_plist);
- defsubr (&Ssymbol_name);
- defsubr (&Smakunbound);
- defsubr (&Sfmakunbound);
- defsubr (&Sboundp);
- defsubr (&Sglobally_boundp);
- defsubr (&Sfboundp);
- defsubr (&Sfset);
- defsubr (&Sdefine_function);
- defsubr (&Ssetplist);
- defsubr (&Ssymbol_value_in_buffer);
- defsubr (&Ssymbol_value);
- defsubr (&Sset);
- defsubr (&Sdefault_boundp);
- defsubr (&Sdefault_value);
- defsubr (&Sset_default);
- defsubr (&Ssetq_default);
- defsubr (&Smake_variable_buffer_local);
- defsubr (&Smake_local_variable);
- defsubr (&Skill_local_variable);
- defsubr (&Slocal_variable_p);
- defsubr (&Sdefvaralias);
- defsubr (&Svariable_alias);
- defsubr (&Sindirect_variable);
- }
-
- /* Create and initialize a variable whose value is forwarded to C data */
- void
- defvar_mumble (CONST char *namestring,
- CONST void *magic, int sizeof_magic)
- {
- Lisp_Object kludge;
- Lisp_Object sym = Fintern (make_pure_pname ((Bufbyte *) namestring,
- strlen (namestring),
- 1),
- Qnil);
-
- /* Check that magic points somewhere we can represent as a Lisp pointer */
- XSETOBJ (kludge, Lisp_Record, magic);
- if (magic != (CONST void *) XPNTR (kludge))
- {
- /* This might happen on DATA_SEG_BITS machines. */
- /* abort (); */
- /* Copy it to somewhere which is representable. */
- void *f = xmalloc (sizeof_magic);
- memcpy (f, magic, sizeof_magic);
- XSETOBJ (XSYMBOL (sym)->value, Lisp_Record, f);
- }
- else
- XSETOBJ (XSYMBOL (sym)->value, Lisp_Record, magic);
- }
-
- void
- vars_of_symbols (void)
- {
- DEFVAR_LISP ("obarray", &Vobarray,
- "Symbol table for use by `intern' and `read'.\n\
- It is a vector whose length ought to be prime for best results.\n\
- The vector's contents don't make sense if examined from Lisp programs;\n\
- to find all the symbols in an obarray, use `mapatoms'.");
- /* obarray has been initialized long before */
- }
-